package com.niiwoo.civet.account.service.local.recharge;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.activity.event.constant.BizEventRabbitConstant;
import com.niiwoo.activity.event.dto.request.RechargeEventReqDTO;
import com.niiwoo.activity.event.enums.RechargeTypeEventEnum;
import com.niiwoo.activity.event.enums.UserRoleTypeEventEnum;
import com.niiwoo.activity.event.enums.YesOrNoEnum;
import com.niiwoo.activity.stage.dto.request.notice.NoviceTaskRecordRequestDTO;
import com.niiwoo.activity.stage.enums.activity.NoviceTaskPrizeEnum;
import com.niiwoo.civet.account.dao.entity.*;
import com.niiwoo.civet.account.dao.mapper.*;
import com.niiwoo.civet.account.dto.RechargeAccountTotalDTO;
import com.niiwoo.civet.account.dto.bill.AddBillAndChangeBalanceDTO;
import com.niiwoo.civet.account.dto.bill.AddBillDetailDTO;
import com.niiwoo.civet.account.dto.common.ManualHandleRecordDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.dto.common.PayChannelDTO;
import com.niiwoo.civet.account.dto.request.RechargeAccountTypeRequestDTO;
import com.niiwoo.civet.account.dto.request.RechargeRecordRequestDTO;
import com.niiwoo.civet.account.dto.request.UpdateRechargeRequestDTO;
import com.niiwoo.civet.account.dto.response.*;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.civet.base.enums.CommonOrderStatusEnum;
import com.niiwoo.civet.trade.constant.RabbitConstant;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.request.RechargeRequest;
import com.niiwoo.tripod.lanmao.response.QueryRechargeResponse;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by lujing on 2017/11/8.
 */
@Service
public class RechargeLocalService {
    private static final Logger logger = LoggerFactory.getLogger(RechargeLocalService.class);

    @Autowired
    private RechargeOrderMapperExt rechargeOrderMapperExt;

    @Autowired
    private PayChannelMapperExt payChannelMapperExt;
    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;

    @Autowired
    private BankCardMapperExt bankCardMapperExt;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private AccountService accountService;
    @Autowired
    private BillFacade billFacade;
    @Autowired
    private ManualHandleRecordMapper manualHandleRecordMapper;
    @Autowired
    private PrivacyMasks privacyMasks;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private BankTypeMapperExt bankTypeMapperExt;
    @Autowired
    private ErrorCodeConfigMapper errorCodeConfigMapper;

    /**
     * 充值订单初始化
     */
    @Transactional(rollbackFor = Exception.class)
    public void initRechargeOrder(RechargeRequest rechargeRequest, String userId, byte businessType, String mobile, String realName, Date expiredTime) {
        logger.info("充值订单初始化initRechargeOrder rechargeRequest ={},userId = {},businessType = {},mobile = {},realName = {}", JSONObject.toJSONString(rechargeRequest), userId, businessType, mobile, realName);
        RechargeOrder rechargeOrder = new RechargeOrder();
        rechargeOrder.setId(snowflakeIdWorker.nextId());
        rechargeOrder.setRequestNo(rechargeRequest.getRequestNo());
        rechargeOrder.setUserId(userId);
        AccountBase accountBase = accountService.loadAccountByAccountNo(rechargeRequest.getPlatformUserNo());
        if (accountBase != null) {
            rechargeOrder.setAccountId(accountBase.getId());
            rechargeOrder.setAccountRole(accountBase.getAccountRole());
        } else {
            throw new BizException("ACC40006");
        }
        BankCard bankCard;
        if (accountBase.getAccountType().equals(AccountTypeEnum.ENTERPRISE.getValue())
                || !OrgConstant.NIIWOO_ORG_ID.equals(accountBase.getOrgId())) {
            bankCard = bankCardMapperExt.selectOrgUserBankCard(accountBase.getId());
        } else {
            bankCard = bankCardMapperExt.selectSimpleUserBankCard(userId);
        }
        if (bankCard != null) {
            rechargeOrder.setBankCardId(bankCard.getId());
            rechargeOrder.setBankCode(bankCard.getBankCode());
        } else {
            throw new BizException("ACC40007");
        }
        rechargeOrder.setBusinessType(businessType);
        rechargeOrder.setRechargeWay(rechargeRequest.getRechargeWay().getValue());
        rechargeOrder.setMobileNo(privacyMasks.encryptPrivacy(mobile));
        rechargeOrder.setRealName(realName);
        PayChannel payChannel = payChannelMapperExt.queryPayChannelByCode(rechargeRequest.getExpectPayCompany().name());
        if (payChannel != null) {
            rechargeOrder.setPayChannelId(payChannel.getId());
            rechargeOrder.setPayChannelCode(payChannel.getChannelCode());
        } else {
            //充值通道查询异常
            throw new BizException("ACC40000");
        }
        rechargeOrder.setAmount(rechargeRequest.getAmount());
        rechargeOrder.setStatus(CommonOrderStatusEnum.PROCESS.getValue());
        rechargeOrder.setCreateTime(new Date());
        rechargeOrder.setExpiredTime(expiredTime);
        rechargeOrderMapperExt.insertSelective(rechargeOrder);
    }

    /**
     * 更新充值订单记录
     *
     * @param updateRechargeRequestDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public UpdateRechargeResponseDTO updateRechargeOrder(UpdateRechargeRequestDTO updateRechargeRequestDTO) {
        logger.info("更新充值订单记录:" + JSON.toJSONString(updateRechargeRequestDTO));
        //通过订单号查询充值记录
        RechargeOrder rechargeOrder = rechargeOrderMapperExt.queryRechargeOrderByRequestNo(updateRechargeRequestDTO.getRequestNo());
        if (rechargeOrder == null) {
            throw new BizException("ACC40002");
        }
        logger.info("订单对象记录:" + JSON.toJSONString(rechargeOrder));
        if (rechargeOrder != null) {
            //锁记录-通过主键
            rechargeOrder = rechargeOrderMapperExt.selectByPrimaryKeyForUpdate(rechargeOrder.getId());
            UpdateRechargeResponseDTO updateRechargeResponseDTO = new UpdateRechargeResponseDTO();
            if (CommonOrderStatusEnum.PROCESS.getValue().equals(rechargeOrder.getStatus()) || CommonOrderStatusEnum.FAILURE.getValue().equals(rechargeOrder.getStatus())) {
                String status = updateRechargeRequestDTO.getRechargeStatusEnum();
                if ("SUCCESS".equals(status)) {
                    rechargeOrder.setStatus(CommonOrderStatusEnum.SUCCESS.getValue());
                    rechargeOrder.setSuccessTime(new Date());
                    rechargeOrder.setUpdateTime(new Date());
                    if (updateRechargeRequestDTO.getEndType() == null) {
                        rechargeOrder.setEndType(OrderEndTypeEnum.AUTO.getValue());
                    } else {
                        rechargeOrder.setEndType(updateRechargeRequestDTO.getEndType());
                        rechargeOrder.setEndTime(new Date());
                        //保存异常处理的信息
                        saveManualRecord(updateRechargeRequestDTO, rechargeOrder);
                    }
                    if (StringUtils.isEmpty(updateRechargeRequestDTO.getAccountNo())) {
                        AccountBase accountBase = accountService.loadAccountByIdForUpdate(rechargeOrder.getAccountId());
                        if (accountBase != null) {
                            updateRechargeRequestDTO.setAccountNo(accountBase.getAccountNo());
                        }
                    }
                    AccountBase accountBase = accountService.loadAccountByAccountNo(updateRechargeRequestDTO.getAccountNo());
                    if (accountBase == null) {
                        throw new BizException("ACC40004");
                    }
                    if (accountBase != null) {
                        logger.info("充值账户信息:" + JSON.toJSONString(accountBase));
                        rechargeOrder.setAccountRole(accountBase.getAccountRole());
                        logger.info("更新充值记录:" + JSON.toJSONString(rechargeOrder));
                        rechargeOrderMapperExt.updateByPrimaryKeySelective(rechargeOrder);
                        try {
                            BillSecondSubjectEnum billSecondSubjectEnum;
                            logger.info("平台账户充值", accountBase.getAccountRole());
                            if (accountBase.getAccountRole().equals(UserRoleEnum.PLATFORM_FUNDS_TRANSFER.getValue())) {
                                billSecondSubjectEnum = BillSecondSubjectEnum.PLATFORM_RECHARGE;
                            } else if (accountBase.getAccountRole().equals(UserRoleEnum.GUARANTEECORP.getValue())) {
                                logger.info("担保机构充值", accountBase.getAccountRole());
                                billSecondSubjectEnum = BillSecondSubjectEnum.GUARANTEE_AGENCY_RECHARGE;
                            } else if (accountBase.getAccountRole().equals(UserRoleEnum.COLLABORATOR.getValue())) {
                                logger.info("合作机构充值", accountBase.getAccountRole());
                                billSecondSubjectEnum = BillSecondSubjectEnum.COOPERATE_AGENCY_RECHARGE;
                            } else {
                                logger.info("个人充值", accountBase.getAccountRole());
                                billSecondSubjectEnum = BillSecondSubjectEnum.USER_RECHARGE;
                            }

                            //变更余额 + 记账
                            AddBillDetailDTO addBillDetailDTO = new AddBillDetailDTO();
                            addBillDetailDTO.setAmount(rechargeOrder.getAmount());
                            addBillDetailDTO.setBillSecondSubjectEnum(billSecondSubjectEnum);
                            addBillDetailDTO.setRemark2(BillRemark3Enum.RECHARGE_INITIATIVE_TYPE.getDesc());

                            AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
                            billDTO.setAccountId(accountBase.getId());
                            billDTO.setAmount(rechargeOrder.getAmount());
                            billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
                            billDTO.setOrderId(rechargeOrder.getId());
                            billDTO.setOrderType(OrderTypeEnum.RECHARGE);
                            billDTO.setRequestNo(updateRechargeRequestDTO.getRequestNo());
                            billDTO.setStatus(BillStatusEnum.SUCCESS);
                            billDTO.setChannelCode(ChannelCodeEnum.APP);
                            billDTO.setAddBillDetailDTOList(Arrays.asList(addBillDetailDTO));
                            billFacade.addBillAndChangeBalance(billDTO);

                        } catch (Exception ex) {
                            logger.error("充值记账异常{}", ex);
                            throw new BizException("ACC40001");
                        }

                        //累计财富计算
                        MoneyTotalDTO moneyTotalDTO = new MoneyTotalDTO();
                        moneyTotalDTO.setAccountId(accountBase.getId());
                        moneyTotalDTO.setAmount(rechargeOrder.getAmount());
                        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.RECHARGE_TOTAL);
                        moneyTotalDTO.setUserId(accountBase.getUserId());
                        logger.info("累计财富计算updateRechargeOrder-moneyTotalDTO{}", JSONObject.toJSONString(moneyTotalDTO));
                        moneyTotalLocalService.moneyTotal(moneyTotalDTO);

                        sendRechargeEventMq(rechargeOrder,accountBase);
                    }

                } else if ("FAIL".equals(status)) {
                    logger.info("状态updateRechargeOrder status:{},requestNO:{}", status,updateRechargeRequestDTO.getRequestNo());
                    rechargeOrder.setStatus(CommonOrderStatusEnum.FAILURE.getValue());
                    rechargeOrder.setUpdateTime(new Date());
                    rechargeOrder.setErrorCode(updateRechargeRequestDTO.getErrorCode());
                    rechargeOrder.setErrorMessage(updateRechargeRequestDTO.getErrorMessage());
                    rechargeOrder.setChannelErrorCode(updateRechargeRequestDTO.getChannelErrorCode());
                    rechargeOrder.setChannelErrorMessage(updateRechargeRequestDTO.getChannelErrorMessage());
                    rechargeOrderMapperExt.updateByPrimaryKeySelective(rechargeOrder);

//                    try{ // V-5.6.0 存管错误码转换
//                        ErrorCodeConfigExample example = new ErrorCodeConfigExample();
//                        ErrorCodeConfigExample.Criteria criteria = example.createCriteria();
//                        criteria.andErrorCodeEqualTo(updateRechargeRequestDTO.getErrorCode());
//                        criteria.andDisableFlagEqualTo(Byte.valueOf("0")); //可用
//                        criteria.andErrorTypeEqualTo(Byte.valueOf("1"));
//                        List<ErrorCodeConfig> errorCodeConfigList = errorCodeConfigMapper.selectByExample(example);
//                        if( null == errorCodeConfigList || errorCodeConfigList.size() == 0 ){
//                            logger.info("充值报文错误编码翻译失败：{}",JSON.toJSONString(rechargeOrder));
//                            criteria.andErrorCodeEqualTo("sys-0000"); //固定值
//                            errorCodeConfigList = errorCodeConfigMapper.selectByExample(example);
//                        }
//                        updateRechargeResponseDTO.setErrorCode(updateRechargeRequestDTO.getErrorCode());
//                        updateRechargeResponseDTO.setErrorMessage(errorCodeConfigList.get(0).getErrorMessage());
//                        updateRechargeResponseDTO.setErrorSolution(errorCodeConfigList.get(0).getSolution());
//                    }catch(Exception expect){
//                        //错误编码转换异常不应影响充值状态更新事务
//                        updateRechargeResponseDTO.setErrorCode("SYS-0000");
//                        updateRechargeResponseDTO.setErrorMessage("其它错误，详情可咨询客服");
//                        updateRechargeResponseDTO.setErrorSolution("其它错误，请重新发起充值。若仍充值失败，请点击底部联系客服。");
//                        logger.error("充值报文错误编码翻译异常：{}",JSON.toJSONString(rechargeOrder));
//
//                    }

                }else if("PENDDING".equals(status)){
                    logger.info("状态updateRechargeOrder{},支付中-暂不处理", status);
                    logger.info("状态updateRechargeOrder status:{},requestNO:{},支付中-暂不处理", status,updateRechargeRequestDTO.getRequestNo());
                }
            }
            //UpdateRechargeResponseDTO updateRechargeResponseDTO = new UpdateRechargeResponseDTO();
            updateRechargeResponseDTO.setRequestNo(updateRechargeRequestDTO.getRequestNo());
            updateRechargeResponseDTO.setOrderId(rechargeOrder.getId());
            updateRechargeResponseDTO.setAmount(updateRechargeRequestDTO.getAmount());
            updateRechargeResponseDTO.setStatus(rechargeOrder.getStatus());
            updateRechargeResponseDTO.setUserId(rechargeOrder.getUserId());
            logger.info("充值处理完毕，返回前端{}", JSONObject.toJSONString(updateRechargeResponseDTO));

            return updateRechargeResponseDTO;
        }
        return null;
    }

    /**
     * 后台处理充值异常情况
     *
     * @param updateRechargeRequestDTO
     * @param rechargeOrder
     */
    private void saveManualRecord(UpdateRechargeRequestDTO updateRechargeRequestDTO, RechargeOrder rechargeOrder) {
        logger.info("后台处理充值异常情况saveManualRecord updateRechargeRequestDTO = {},rechargeOrder = {}", updateRechargeRequestDTO, rechargeOrder);
        ManualHandleRecordDTO manualHandleRecordDTO = updateRechargeRequestDTO.getManualHandleRecordDTO();
        logger.info("saveManualRecord manualHandleRecordDTO={}", manualHandleRecordDTO);
        if (manualHandleRecordDTO != null) {
            ManualHandleRecord manualHandleRecord = new ManualHandleRecord();
            manualHandleRecord.setId(snowflakeIdWorker.nextId());
            manualHandleRecord.setOrderId(rechargeOrder.getId());
            manualHandleRecord.setOrderType(ManualHandleOrderTypeEnum.RECHARGE.getValue());
            manualHandleRecord.setUserId(rechargeOrder.getUserId());
            manualHandleRecord.setHandleType(ManualHandleTypeEnum.RECHARGE_SUCCESS.getValue());
            manualHandleRecord.setHandleReason(manualHandleRecordDTO.getHandleReason());
            manualHandleRecord.setHandleManagerId(manualHandleRecordDTO.getHandleManagerId());
            manualHandleRecord.setHandleManagerName(manualHandleRecordDTO.getHandleManagerName());
            manualHandleRecord.setCreateTime(new Date());
            int result = manualHandleRecordMapper.insertSelective(manualHandleRecord);
            if (result != 1) {
                logger.error("充值异常处理保存失败{}", rechargeOrder.getId());
                throw new BizException("ACC40003");
            }
        }
    }

    /**
     * 查询用户充值列表
     *
     * @param rechargeRecordRequestDTO
     * @return
     */
    @Transactional
    public PageResponseDTO<RechargeRecordResponseDTO> rechargeRecordList(RechargeRecordRequestDTO rechargeRecordRequestDTO) {
        logger.info("查询用户充值列表rechargeRecordList{}", JSONObject.toJSONString(rechargeRecordRequestDTO));
        PageResponseDTO<RechargeRecordResponseDTO> pageResponseDTO = new PageResponseDTO<>();
        List<RechargeRecordResponseDTO> dtoList = new ArrayList<>();

        List<Long> accountIds = new ArrayList<>();
        if(OrgConstant.NIIWOO_ORG_ID.equals(rechargeRecordRequestDTO.getOrgId())){
            List<AccountBase> accountBaseList = accountService.listNiiwooAccountByUserId(rechargeRecordRequestDTO.getUserId());
            accountIds = accountBaseList.stream().map(AccountBase::getId).collect(Collectors.toList());
            accountIds.add(-1L);
        }else{
            AccountBase accountBase = accountService.loadOrgAccount(rechargeRecordRequestDTO.getUserId(),rechargeRecordRequestDTO.getOrgId());
            accountIds.add(accountBase.getId());
        }
        rechargeRecordRequestDTO.setAccountIds(accountIds);

        int count = rechargeOrderMapperExt.countRechargeByUserIdAndAccountIds(rechargeRecordRequestDTO.getUserId(),accountIds);
        logger.info("rechargeRecordList count = {}", count);
        List<RechargeOrder> rechargeOrderList = rechargeOrderMapperExt.queryRechargeByUserIdAndAccountIds(rechargeRecordRequestDTO);
        logger.info("rechargeRecordList rechargeOrderList = {}", JSONObject.toJSONString(rechargeOrderList));
        if (!rechargeOrderList.isEmpty()) {
            rechargeOrderList.stream().forEach(o -> {
                RechargeRecordResponseDTO dto = new RechargeRecordResponseDTO();
                dto.setAmount(o.getAmount());
                dto.setTime(o.getCreateTime());
                dto.setStatus(o.getStatus());
                AccountBase accountBase = accountService.loadAccountById(o.getAccountId());
                if (accountBase != null) {
                    if (UserRoleEnum.INVESTOR.getValue().equals(accountBase.getAccountRole())) {
                        dto.setAccountRole(UserRoleEnum.INVESTOR.getValue());
                    } else if (UserRoleEnum.BORROWERS.getValue().equals(accountBase.getAccountRole())) {
                        dto.setAccountRole(UserRoleEnum.BORROWERS.getValue());
                    } else if (UserRoleEnum.GUARANTEECORP.getValue().equals(accountBase.getAccountRole())) {
                        dto.setAccountRole(UserRoleEnum.GUARANTEECORP.getValue());
                    }
                }
                dtoList.add(dto);
            });
        }
        pageResponseDTO.setItems(dtoList);
        pageResponseDTO.measureTotalPage(count, rechargeRecordRequestDTO.getPageSize());
        return pageResponseDTO;
    }

    @Transactional
    public RechargeStatisticsResponseDTO statisticsRecharge(String userId, String orgId){
        RechargeStatisticsResponseDTO resultDTO = new RechargeStatisticsResponseDTO();
        List<Long> accountIds = new ArrayList<>();
        if(OrgConstant.NIIWOO_ORG_ID.equals(orgId)){
            List<AccountBase> accountBaseList = accountService.listNiiwooAccountByUserId(userId);
            accountIds = accountBaseList.stream().map(AccountBase::getId).collect(Collectors.toList());
            accountIds.add(-1L);
        }else{
            AccountBase accountBase = accountService.loadOrgAccount(userId,orgId);
            accountIds.add(accountBase.getId());
        }
        QueryMoneyTotalResponseDTO queryMoneyTotalResponseDTO = moneyTotalLocalService.queryMoneyTotal(userId,accountIds.get(0));

        //List<Byte> successStatus = new ArrayList<>();
        //successStatus.add((byte)1);
        List<Byte> failStatus = new ArrayList<>();
        failStatus.add((byte)2);
        failStatus.add((byte)3);
        //BigDecimal successTotal= rechargeOrderMapperExt.statisticsRecharge(userId,successStatus,accountIds);
        BigDecimal failTotal= rechargeOrderMapperExt.statisticsRecharge(userId,failStatus,accountIds);
        resultDTO.setSuccessTotal(queryMoneyTotalResponseDTO.getRechargeTotal());
        resultDTO.setFailTotal(failTotal);
        return resultDTO;
    }
    /**
     * 获取所有在处理中的订单
     *
     * @return
     */
    public List<RechargeUpdateResponseDTO> queryOrderByStatus() {
        //获取所有处理中的充值订单，查询在处理中的标的，大于5分钟小于2天
        return rechargeOrderMapperExt.queryOrderByStatus();

    }

    /**
     * 根据存管查取的状态更新订单
     *
     * @param response
     * @param responseDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrder(QueryRechargeResponse response, RechargeUpdateResponseDTO responseDTO) {
        logger.info("根据存管查取的状态更新订单updateOrder{},{},{}", JSONObject.toJSON(response), JSONObject.toJSON(responseDTO), responseDTO.getRequestNo());
        List<QueryRechargeResponse.RechargeDetail> rechargeDetails = response.getRecords();
        if (!rechargeDetails.isEmpty()) {
            for (QueryRechargeResponse.RechargeDetail detail : rechargeDetails) {
                String status = detail.getStatus();
                logger.info("updateOrder根据存管查取的状态更新订单状态status = {},requestNo ={} ", status,responseDTO.getRequestNo());
                if ("SUCCESS".equals(status)) {
                    UpdateRechargeRequestDTO updateRechargeRequestDTO = new UpdateRechargeRequestDTO();
                    updateRechargeRequestDTO.setRequestNo(responseDTO.getRequestNo());
                    updateRechargeRequestDTO.setAmount(detail.getAmount());
                    updateRechargeRequestDTO.setAccountNo(detail.getPlatformUserNo());
                    updateRechargeRequestDTO.setRechargeStatusEnum(status);
                    updateRechargeRequestDTO.setEndType(OrderEndTypeEnum.FAIL.getValue());
                    updateRechargeOrder(updateRechargeRequestDTO);
                }
                //存管明确表示失败
                if ("FAIL".equals(status)) {
                    logger.info("updateOrder根据存管查取的状态更新订单失败status = {},requestNo ={}", status,responseDTO.getRequestNo());
                    RechargeOrder rechargeOrder = rechargeOrderMapperExt.queryRechargeOrderByRequestNo(responseDTO.getRequestNo());
                    if (rechargeOrder != null) {
                        rechargeOrder.setEndTime(new Date());
                        rechargeOrder.setEndType(OrderEndTypeEnum.FAIL.getValue());
                        rechargeOrder.setStatus(CommonOrderStatusEnum.FAILURE.getValue());
                        rechargeOrderMapperExt.updateByPrimaryKeySelective(rechargeOrder);
                    }
                }
            }
        }
    }

    /**
     * 关闭订单
     *
     * @param requestNo
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRechargeOrder(String requestNo) {
        logger.info("updateRechargeOrder requestNo = {}", requestNo);
        RechargeOrder rechargeOrder = rechargeOrderMapperExt.queryRechargeOrderByRequestNo(requestNo);
        logger.info("updateRechargeOrder rechargeOrder = {}", JSONObject.toJSONString(rechargeOrder));
        if (rechargeOrder != null) {
            rechargeOrder.setEndTime(new Date());
            rechargeOrder.setEndType(OrderEndTypeEnum.FAIL.getValue());
            rechargeOrder.setStatus(CommonOrderStatusEnum.CLOSE.getValue());
            rechargeOrderMapperExt.updateByPrimaryKeySelective(rechargeOrder);
        }
    }


    /**
     * 查询用户最新的充值成功的记录
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public RechargeOrderDTO userRechrageSuccRecordWithOrgId(String userId,String orgId) {
        logger.info("userRechrageSuccRecord{}", userId);
        List<Long> accountIds = getAccountIdByUserIdAndOrgId(userId,orgId);

        RechargeOrder rechargeOrder = rechargeOrderMapperExt.userRechrageSuccRecordWithAccountIds(userId,accountIds);
        logger.info("userRechrageSuccRecord   rechargeOrder = {}", JSONObject.toJSONString(rechargeOrder));
        if (rechargeOrder != null) {
            RechargeOrderDTO rechargeOrderDTO = new RechargeOrderDTO();
            rechargeOrderDTO.setUserId(userId);
            rechargeOrderDTO.setAmount(rechargeOrder.getAmount());
            rechargeOrderDTO.setAccountId(rechargeOrder.getAccountId());
            rechargeOrderDTO.setAccountRole(rechargeOrder.getAccountRole());
            rechargeOrderDTO.setRequestNo(rechargeOrder.getRequestNo());
            return rechargeOrderDTO;
        }
        return null;
    }


    public PayChannelDTO selectPayChannelCode() {
        PayChannel payChannel = payChannelMapperExt.selectPayChannelCode();
        //充值通道查询异常
        if(payChannel == null){
            throw new BizException("ACC40000");
        }
        PayChannelDTO payChannelDTO = new PayChannelDTO();
        payChannelDTO.setPayChannelCode(payChannel.getChannelCode());
        logger.info("个人网银充值支付通道为:{}",payChannel.getChannelCode());
        return payChannelDTO;
    }

    /**
     * 查询用户首次充值成功记录
     * @param userId
     * @return
     */
    public RechargeOrderDTO queryFirstRechrageSuccessRecord(String userId){
        RechargeOrderDTO rechargeOrderDTO = null;
        RechargeOrder rechargeOrder=rechargeOrderMapperExt.queryFirstRechrageSuccessRecord(userId);
        if(rechargeOrder!=null){
            rechargeOrderDTO = new RechargeOrderDTO();
            try {
                BeanUtils.copyProperties(rechargeOrderDTO,rechargeOrder);
            } catch (Exception e){
                logger.error("查询用户首次充值记录,用户ID={},转换RechargeOrderDTO报错,原因={}",userId,e);
            }
        }

        return rechargeOrderDTO;
    }

    /**
     * 查询用户充值成功总金额
     * @param userId
     * @return
     */
    public BigDecimal queryUserTotalRechrageAmount(String userId){
        return rechargeOrderMapperExt.queryUserTotalRechrageAmount(userId);
    }

    /**
     * 根据用户ID和机构ID查询用户充值成功总金额
     *
     * @param userId
     * @param orgId
     * @return
     */
    public BigDecimal queryUserTotalRechrageAmountWithOrgId(String userId,String orgId){
        List<Long> accountIds = getAccountIdByUserIdAndOrgId(userId,orgId);
        return rechargeOrderMapperExt.queryUserTotalRechrageAmountWithAccountIds(userId,accountIds);
    }

    /**
     * 发送充值事件的消息服务
     * @param rechargeOrder
     * @param accountBase
     */
    public void sendRechargeEventMq(RechargeOrder rechargeOrder,AccountBase accountBase) {
        RechargeEventReqDTO rechargeEventReqDTO = new RechargeEventReqDTO();
        rechargeEventReqDTO.setRechargeId(rechargeOrder.getId());
        rechargeEventReqDTO.setUserId(rechargeOrder.getUserId());
        rechargeEventReqDTO.setUpdateDate(new Date());
        rechargeEventReqDTO.setAmount(rechargeOrder.getAmount());
        rechargeEventReqDTO.setBankCode(rechargeOrder.getBankCode());

        if(Objects.nonNull(rechargeOrder.getPayChannelId())) {
            PayChannel payChannel = payChannelMapperExt.selectByPrimaryKey(rechargeOrder.getPayChannelId());
            rechargeEventReqDTO.setPayChannelName(payChannel.getChannelName());
        }else {
            rechargeEventReqDTO.setPayChannelName(null);
        }

        if(Objects.nonNull(rechargeOrder.getBankCardId())) {
            BankType bankType = bankTypeMapperExt.selectBankTypeByCode(rechargeOrder.getBankCode());
            rechargeEventReqDTO.setBankName(bankType.getBankName());
        }else {
            rechargeEventReqDTO.setBankName(null);
        }

        rechargeEventReqDTO.setRechargeDate(rechargeOrder.getCreateTime());
        rechargeEventReqDTO.setRechargeTypeEventEnum(RechargeTypeEventEnum.general);
        rechargeEventReqDTO.setUserRoleTypeEventEnum(UserRoleTypeEventEnum.valueOf(accountBase.getAccountRole()));
        RechargeRecordRequestDTO requestDTO = new RechargeRecordRequestDTO();
        requestDTO.setUserId(rechargeOrder.getUserId());
        requestDTO.setStatus(CommonOrderStatusEnum.SUCCESS.getValue());
        requestDTO.setId(rechargeOrder.getId());
        Integer count = rechargeOrderMapperExt.countRechargeByUserIdAndStatus(requestDTO);
        rechargeEventReqDTO.setFirstRechargeYesOrNoEnum(count>0? YesOrNoEnum.NO:YesOrNoEnum.YES);

        try {
            rabbitTemplate.convertAndSend(BizEventRabbitConstant.Exchange.BIZ_EVENT_DIRECT_EXCHANGE, BizEventRabbitConstant.Key.BIZ_EVENT_RECHARGE_KEY, rechargeEventReqDTO);
        } catch (AmqpException e) {
            logger.error("充值事件同步amountExchangeDTO:{}", JSON.toJSONString(rechargeEventReqDTO), e);
        }
        try {
            NoviceTaskRecordRequestDTO dto = new NoviceTaskRecordRequestDTO();
            dto.setUserId(rechargeOrder.getUserId());
            dto.setTaskType(NoviceTaskPrizeEnum.FRIST_RECHARGE.getCode());
            rabbitTemplate.convertAndSend(RabbitConstant.Exchange.NOVICE_TASK_RECORD, RabbitConstant.RoutingKey.NOVICE_TASK_RECORD, dto);
        } catch (Exception e) {
            logger.error("novice_task_activity首次充值###调用新手任务###请求失败,userId={}, errorMessage={}", rechargeOrder.getUserId(), e.getMessage());
        }
    }

    /**
     * 根据userId和orgId获取账户ID列表
     *
     * @param userId
     * @param orgId
     * @return
     */
    public List<Long> getAccountIdByUserIdAndOrgId(String userId,String orgId){
        List<Long> accountIds = new ArrayList<>();
        if(OrgConstant.NIIWOO_ORG_ID.equals(orgId)){
            List<AccountBase> accountBaseList = accountService.listNiiwooAccountByUserId(userId);
            accountIds = accountBaseList.stream().map(AccountBase::getId).collect(Collectors.toList());
        }else{
            AccountBase accountBase = accountService.loadOrgAccount(userId,orgId);
            accountIds.add(accountBase.getId());
        }
        return accountIds;
    }

    /**
     * 查询充值中的订单列表
     * @param accountId
     * @return
     */
    public List<RechargeOrder> queryRechargingOrderList(Long accountId){
        RechargeOrderExample example = new RechargeOrderExample();
        RechargeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andAccountIdEqualTo(accountId);
        criteria.andStatusEqualTo(RechargeOrderStatusEnum.PENDDING.getValue());

        return rechargeOrderMapperExt.selectByExample(example);

    }

    public RechargeOrder queryLatelyRechargeAccountType(RechargeAccountTypeRequestDTO rechargeAccountTypeRequestDTO){
        RechargeAccountTotalDTO rechargeAccountTotalDTO = new RechargeAccountTotalDTO();
        rechargeAccountTotalDTO.setUserId(rechargeAccountTypeRequestDTO.getUserId());
        rechargeAccountTotalDTO.setAccountIds(rechargeAccountTypeRequestDTO.getAccountIds());
        return rechargeOrderMapperExt.queryLatelyRecharge(rechargeAccountTotalDTO);
    }

    public RechargeMoneyVerifyResponseDTO getStatisticsRechargeMoneyByUserId(RechargeAccountTypeRequestDTO rechargeAccountTypeRequestDTO){
        RechargeAccountTotalDTO rechargeAccountTotalDTO = new RechargeAccountTotalDTO();
        rechargeAccountTotalDTO.setUserId(rechargeAccountTypeRequestDTO.getUserId());
        rechargeAccountTotalDTO.setAccountIds(rechargeAccountTypeRequestDTO.getAccountIds());
        BigDecimal currentDayMoney = rechargeOrderMapperExt.queryCurrentDayRechargeMoney(rechargeAccountTotalDTO);
        BigDecimal currentMonthMoney = rechargeOrderMapperExt.queryCurrentMonthRechargeMoney(rechargeAccountTotalDTO);

        RechargeMoneyVerifyResponseDTO responseDTO = new RechargeMoneyVerifyResponseDTO();
        responseDTO.setDayTotalRechargeMoney(currentDayMoney);
        responseDTO.setMoneyTotalRechargeMoney(currentMonthMoney);
        return responseDTO;
    }

    public BankInfoRespDTO getBankInfoByOrderId(Long rechargeOrderId){
        // 根据订单id查询充值订单
        RechargeOrder rechargeOrder = rechargeOrderMapperExt.selectByPrimaryKey(rechargeOrderId);
        if(Objects.nonNull(rechargeOrder) && Objects.nonNull(rechargeOrder.getBankCardId())){
            // 根据订单中的bankCardId查询银行卡信息
            BankCard bankCard = bankCardMapperExt.selectByPrimaryKey(rechargeOrder.getBankCardId());
            // 查询银行名称+银行卡号
            BankType bankType = bankTypeMapperExt.selectBankTypeByCode(bankCard.getBankCode());

            //返回
            BankInfoRespDTO bankInfoRespDTO = new BankInfoRespDTO();
            bankInfoRespDTO.setBankNo(privacyMasks.decryptPrivacy(bankCard.getBankAccountNo()));
            bankInfoRespDTO.setBankName(bankType.getBankName());
            return bankInfoRespDTO;
        }

        return null;
    }

    public RechargeOrderDTO queryOrderByOrderId(Long orderId) {
        RechargeOrder rechargeOrder = rechargeOrderMapperExt.selectByPrimaryKeyForUpdate(orderId);
        if (rechargeOrder != null) {
            RechargeOrderDTO rechargeOrderDTO = new RechargeOrderDTO();
            //rechargeOrderDTO.setUserId(rechargeOrder.getUserId());
            org.springframework.beans.BeanUtils.copyProperties(rechargeOrder,rechargeOrderDTO);
            return rechargeOrderDTO;
        }
        return null;
    }

}
